#include "ast/ast.hpp"
#include "ast/visitor.hpp"
#include "parser/lexer.hpp"
#include "runtime/dict_object.hpp"
#include "env.hpp"
#include "type/type.hpp"

ListNode::ListNode() {
    _node_list = new vector<Node*>();
}

void ListNode::add(Node* n) {
    _node_list->push_back(n);
}

void Node::accept(Visitor* visitor) {
    printf("Should not reach here.\n");
    exit(1);
}

VarNode::VarNode(Token* t) {
    _name = new char[t->_length + 1];
    _name[t->_length] = '\0';
    strncpy(_name, t->_value, t->_length);
}

VarDefNode::VarDefNode(Token* t) {
    _name = new char[t->_length + 1];
    _name[t->_length] = '\0';
    strncpy(_name, t->_value, t->_length);

    _type = NULL;
    _init = NULL;
}

TypeDefNode::TypeDefNode(Token* t) {
    _name = new char[t->_length + 1];
    _name[t->_length] = '\0';
    strncpy(_name, t->_value, t->_length);

    _type = NULL;
}

/**
 * Dump functions for all nodes.
 */
void AssignNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void VarNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void LogicOrNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void LogicNotNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void LogicAndNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void BitOrNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void BitXorNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void BitAndNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void LeftShiftNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void RightShiftNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void AddNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void SubNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void MulNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void DivNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void ConstInt::accept(Visitor* visitor) {
    visitor->visit(this);
}

void ConstBool::accept(Visitor* visitor) {
    visitor->visit(this);
}

void ConstString::accept(Visitor* visitor) {
    visitor->visit(this);
}

void ConstChar::accept(Visitor* visitor) {
    visitor->visit(this);
}

void ListNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void LambdaDef::accept(Visitor* visitor) {
    visitor->visit(this);
}

void CallNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void PrintNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void PrintlnNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void IfNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void CmpNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void VarDefNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

void TypeDefNode::accept(Visitor* visitor) {
    visitor->visit(this);
}

/**
 * destructor
 */
BinaryOp::~BinaryOp() {
    if (_left != NULL) {
        delete _left;
        _left = NULL;
    }

    if (_right != NULL) {
        delete _right;
        _right = NULL;
    }
}

ListNode::~ListNode() {
    for (auto it = _node_list->begin(); it != _node_list->end(); it++) {
        delete (*it);
    }

    _node_list->clear();
    delete _node_list;
    _node_list = NULL;
}

ConstInt::~ConstInt() {
    _value = NULL; // this depend on GC.
}

ConstString::~ConstString() {
    _value = NULL; // this depend on GC.
}

ConstChar::~ConstChar() {
    _value = NULL; // this depend on GC.
}

VarNode::~VarNode() {
    if (_name != NULL) {
        delete[] _name;
        _name = NULL;
    }
}

VarDefNode::~VarDefNode() {
    if (_name != NULL) {
        delete[] _name;
        _name = NULL;
    }

    if (_init != NULL) {
        delete _init;
        _init = NULL;
    }
}

TypeDefNode::~TypeDefNode() {
    if (_name != NULL) {
        delete[] _name;
        _name = NULL;
    }
}

LambdaDef::~LambdaDef() {
    if (_param != NULL) {
        delete _param;
        _param = NULL;
    }

    if (_body != NULL) {
        delete _body;
        _body = NULL;
    }
}

CallNode::~CallNode() {
    if (_func_name != NULL) {
        delete _func_name;
        _func_name = NULL;
    }

    if (_param != NULL) {
        delete _param;
        _param = NULL;
    }
}

PrintNode::~PrintNode() {
    if (_body != NULL) {
        delete _body;
        _body = NULL;
    }
}

PrintlnNode::~PrintlnNode() {
    if (_body != NULL) {
        delete _body;
        _body = NULL;
    }
}

IfNode::~IfNode() {
    if (_cond != NULL) {
        delete _cond;
        _cond = NULL;
    }

    if (_then != NULL) {
        delete _then;
        _then = NULL;
    }

    if (_else != NULL) {
        delete _else;
        _else = NULL;
    }
}

